package stupidMineralCollector;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import stupidMineralCollector.gui.ColorRenderer;
import stupidMineralCollector.gui.SimpleColorMap;
import stupidMineralCollector.model.SCV;
import stupidMineralCollector.model.StupidMineralCollector;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;

import jnibwapi.model.Unit;

public class GUI implements ChangeListener {

	private JFrame frame = new JFrame("Pheromones");

	private JPanel panel1 = new JPanel();
	private JPanel panel2 = new JPanel();

	private ColorRenderer[][] tiles = new ColorRenderer[128][128];
	private GridLayout layout = new GridLayout(128, 128);

	private StupidMineralCollector ai;

	private SimpleColorMap colorMap1;
	private SimpleColorMap colorMap2;
	
	private JSlider diffSlider;
	private JLabel diffLabel;
	private JSlider phSlider;
	private JLabel phLabel;
	private JSlider evapSlider;
	private JLabel evapLabel;
	private JSlider minPhSlider;
	private JLabel minPhLabel;
	private JSlider maxPhSlider;
	private JLabel maxPhLabel;
	
	GUI() {

		this.ai = new StupidMineralCollector();
		new Thread(ai).start();
		ai.getPheromoneMap();
		colorMap1 = new SimpleColorMap(0.0, 0.5, Color.black, Color.green);
		colorMap2 = new SimpleColorMap(0.5, 2.0, Color.green, Color.white);
		iniGUI();

	}

	public static void main(String[] args) {
		System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
		new GUI();
	}

	public void iniGUI() {
		System.out.println("Creating Frame!");

		frame = new JFrame("Pheromones");
		frame.setSize(650, 500);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLayout(new BorderLayout());
		panel1.setLayout(layout);
		panel1.setPreferredSize(new Dimension(128*3,128*3));
		
		for (int i = 0; i < tiles.length; i++) {
			for (int j = 0; j < tiles[i].length; j++) {

				tiles[i][j] = new ColorRenderer();
				tiles[i][j].setOpaque(true);

				panel1.add(tiles[i][j], null);

			}

		}
		// Set sliders to change our constants
		Constants c = Constants.getInstance();
		panel2.setLayout(new GridLayout(6*2,2));
		
		diffSlider = new JSlider(JSlider.HORIZONTAL,0,100,(int)(c.getDiffusionRate()*100));
		diffSlider.addChangeListener(this);
		panel2.add(new JLabel("Diffusion"));
		panel2.add(diffSlider);
		panel2.add(new JLabel());
		diffLabel = new JLabel(""+c.getDiffusionRate());
		panel2.add(diffLabel);
		
		phSlider = new JSlider(JSlider.HORIZONTAL,0,5000,(int)(c.getPheromoneOutput()*10));
		phSlider.addChangeListener(this);
		panel2.add(new JLabel("PH-Output"));
		panel2.add(phSlider);
		panel2.add(new JLabel());
		phLabel = new JLabel(""+c.getPheromoneOutput());
		panel2.add(phLabel);
		
		evapSlider = new JSlider(JSlider.HORIZONTAL,0,100,(int)(c.getEvaporationRate()*1000));
		evapSlider.addChangeListener(this);
		panel2.add(new JLabel("Evap"));
		panel2.add(evapSlider);
		panel2.add(new JLabel());
		evapLabel = new JLabel(""+c.getEvaporationRate());
		panel2.add(evapLabel);
		
		minPhSlider = new JSlider(JSlider.HORIZONTAL,0,100,(int)(c.getMinPheromoneLevel()*100));
		minPhSlider.addChangeListener(this);
		panel2.add(new JLabel("Min-PH"));
		panel2.add(minPhSlider);
		panel2.add(new JLabel());
		minPhLabel = new JLabel(""+c.getMinPheromoneLevel());
		panel2.add(minPhLabel);
		
		maxPhSlider = new JSlider(JSlider.HORIZONTAL,0,3000,(int)(c.getMaxPheromoneLevel()*100));
		maxPhSlider.addChangeListener(this);
		panel2.add(new JLabel("Max-PH"));
		panel2.add(maxPhSlider);
		panel2.add(new JLabel());
		maxPhLabel = new JLabel(""+c.getMaxPheromoneLevel());
		panel2.add(maxPhLabel);
						
		frame.add(panel1,BorderLayout.WEST);
		frame.add(panel2,BorderLayout.EAST);
		frame.pack();
		frame.setVisible(true);

		ActionListener action = new ActionListener() {

			@Override
			public synchronized void actionPerformed(ActionEvent e) {
				if (ai.isGameRunning()) {
					Random gen = new Random();

					double[][] pheromoneValues = ai.getPheromoneMap()
							.getCopyOfPheromoneValues();
					frame.getContentPane().setBackground(
							new Color(gen.nextInt(256), gen.nextInt(256), gen
									.nextInt(256)));

					for (int i = 0; i < tiles.length; i++) {
						for (int j = 0; j < tiles[0].length; j++) {
							tiles[i][j]
									.setBackground(getColorForPheromoneLevel(pheromoneValues[j][i]));
						}
					}
					// grab a copy of our data and draw scv + minerals
					Object[] scvs = ai.getSCVs();
					for( Object s: scvs )
					{
						SCV scv = (SCV)s;
						tiles[scv.getTileY()][scv.getTileX()].setBackground( Color.yellow );
					}
					
					Object[] minerals = ai.getMinerals();
					for( Object m: minerals )
					{
						Unit min = (Unit)m;
						tiles[min.getTileY()][min.getTileX()].setBackground( Color.blue );
						
					}
				}
			}
		};

		Timer t = new Timer(100, action);
		t.setRepeats(true);
		t.start();
	}
	
	private Color getColorForPheromoneLevel(double scent) {
		Color result = null;
		Constants c = Constants.getInstance();
		
		if (scent > c.getMaxPheromoneLevel() || scent < c.getMinPheromoneLevel())
			result = Color.black;
		else if (scent < 0.5) 
			result = colorMap1.getColor(scent);
		else
			result = colorMap2.getColor(scent);
		

		return result;
	}

	@Override
	public void stateChanged(ChangeEvent e) {
		Constants c = Constants.getInstance();
		JSlider s = (JSlider)e.getSource();
		if( e.getSource().equals(diffSlider) )
		{
			double value = s.getValue() / 100.0;
			diffLabel.setText(""+value);
			c.setDiffusionRate(value);
		}
		else if( e.getSource().equals(phSlider) )
		{
			double value = s.getValue() / 10.0;
			phLabel.setText(""+value);
			c.setPheromoneOutput(value);
		}
		else if( e.getSource().equals(evapSlider) )
		{
			double value = s.getValue() / 1000.0;
			evapLabel.setText(""+value);
			c.setEvaporationRate(value);
		}
		else if( e.getSource().equals(minPhSlider) )
		{
			double value = s.getValue() / 100.0;
			minPhLabel.setText(""+value);
			c.setMinPheromoneLevel(value);
		}
		else if( e.getSource().equals(maxPhSlider) )
		{
			double value = s.getValue() / 100.0;
			maxPhLabel.setText(""+value);
			c.setMaxPheromoneLevel(value);
		}
	}
}